package com.qingzhuge.file.service;

import com.qingzhuge.common.utils.DateUtil;
import com.qingzhuge.file.FileStorageEnum;
import com.qingzhuge.file.entity.FileStorageConfig;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Date;
import java.util.Objects;
import java.util.UUID;

/**
 * @author : zero.xiao
 * @description : 云存储(支持七牛、阿里云、腾讯云、又拍云)
 * @date :2018/6/8 0008 下午 15:13
 * @modified :
 * @since : 1.0.0
 */
public abstract class BaseFileStorageService {
    protected Logger log = LoggerFactory.getLogger(getClass());
    protected static final String PATH_SEPARATOR = "/";
    protected static final String FILE_SEPARATOR = File.separator;
    /**
     * 云存储配置信息
     */
    protected FileStorageConfig config;

    /**
     * 获取配置前缀
     *
     * @return String
     */
    protected abstract String getPrefix();

    protected abstract String separator();

    public FileStorageEnum getType() {
        return config.getType();
    }

    /**
     * 文件路径
     *
     * @param suffix 后缀
     * @param module 应用模块
     * @param type   文件类型
     * @return 返回上传路径
     */
    public String getPath(String suffix, String module, String type) {
        Date now = new Date();
        StringBuilder path = new StringBuilder(getPrefix());
        if (!config.getLocalPrefix().endsWith(separator())) {
            path.append(separator());
        }
        path.append(module)
                .append(separator())
                .append(type)
                .append(separator());
        //文件路径
        path.append(DateUtil.format(now, "yyyyMMdd"))
                .append(separator())
                .append(DateUtil.format(now, "HHmmssSSS"))
                .append("-")
                //生成uuid
                .append(UUID.randomUUID().toString().replaceAll("-", ""));
        if (StringUtils.isNotBlank(suffix)) {
            path.append(suffix);
        }
        String pathStr = path.toString();
        log.debug("file upload path:{}", pathStr);
        return pathStr;
    }

    /**
     * 文件上传
     *
     * @param data 文件字节数组
     * @param path 文件路径，包含文件名
     * @return 返回http地址
     */
    public abstract String upload(byte[] data, String path);

    /**
     * 文件上传
     *
     * @param file   MultipartFile 文件
     * @param module 业务模块名称
     * @param type   文件类型
     * @return 返回文件地址
     */
    public String upload(MultipartFile file, String module, String type) {
        String filePath = null;
        try {
            String suffix = Objects.requireNonNull(file.getOriginalFilename())
                    .substring(file.getOriginalFilename()
                            .lastIndexOf("."));
            filePath = this.upload(file.getBytes(), getPath(suffix, module, type));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return filePath;
    }

    /**
     * 返回http地址
     *
     * @param data 文件字节数组
     * @param ptah 路径
     * @return 返回http地址
     */
    public String uploadSuffix(byte[] data, String ptah) {
        return upload(data, getPrefix() + separator() + ptah);
    }

    /**
     * 返回http地址
     *
     * @param data     文件字节数组
     * @param fileName 文件名
     * @param suffix   后缀
     * @return 返回http地址
     */
    public String uploadSuffix(byte[] data, String fileName, String suffix) {
        return upload(data, getPrefix() + separator() + fileName + suffix);
    }

    /**
     * 文件上传
     *
     * @param inputStream 字节流
     * @param path        文件路径，包含文件名
     * @return 返回http地址
     */
    public abstract String upload(InputStream inputStream, String path) throws IOException;

    /**
     * 文件上传
     *
     * @param inputStream 字节流
     * @param path        路径
     * @return 返回http地址
     */
    public String uploadSuffix(InputStream inputStream, String path) throws IOException {
        return upload(inputStream, getPrefix() + separator() + path);
    }

    /**
     * 下载文件，流向用户前端
     *
     * @param path         文件路径
     * @param outputStream 输出流，response
     */
    public abstract void download(String path, OutputStream outputStream);

    /**
     * 删除文件
     *
     * @param path 文件路径
     */
    public abstract void delete(String path);

    /**
     * 输出数据流
     *
     * @param in  输入
     * @param out 输出
     */
    protected void writeStream(InputStream in, OutputStream out) {
        try {
            int data;
            while ((data = in.read()) != -1) {
                out.write(data);
            }
        } catch (IOException e) {
            log.debug("down file:{}", e.getMessage());
        } finally {
            try {
                if (out != null) {
                    out.flush();
                    out.close();
                }
                if (in != null) {
                    in.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
